# -*- coding: utf-8 -*-

import os
import re
import multiprocessing

# Used to convert path to object filename.
# some/path/to/foo would become some_path_to_foo
def EscapePath(Path):
	Path = re.sub(r"[^a-zA-Z0-9]+", '_', Path)
	if Path[0] == '_':
		Path = Path[1:]
	return Path

# All warnings, all errors, pedantic, fuck yeah!
E = Environment()
E.Append(CCFLAGS = '-Wall -Wextra -pedantic -funsigned-char -march=native -pthread') #-Wno-unused-private-field
E.Append(CFLAGS = '-std=c11')
E.Append(CXXFLAGS = '-std=c++11')
E.Append(LINKFLAGS = '-pthread')

# Debug / Release build parameters
Debug = int(ARGUMENTS.get('DEBUG', 0))
BinDirectory = None

if Debug:
	BinDirectory = 'Debug'
	E.Append(CCFLAGS = "-ggdb -DDEBUG -D_GLIBCXX_DEBUG")
	E.Append(LINKFLAGS = "-rdynamic")
else:
	BinDirectory = 'Release'
	E.Append(CCFLAGS = "-O3 -DNDEBUG -fdata-sections -ffunction-sections")
	E.Append(LINKFLAGS = "-O3 -s -Wl,--gc-sections")

# Those configs would be parsed
ParseConfigs = [
	'pkg-config --libs sqlite3'
]

# Do the actual parsing
for ParseConfig in ParseConfigs:
	E.ParseConfig(ParseConfig)

# Enable paralell build
SetOption('num_jobs', multiprocessing.cpu_count() + 1)

# All files with this extension would be compiled
SourceExtensions = ['.cpp']

# Skip those directories while looking for source files
SourceSkipDirectories = ['./Tests']

# Treat files containing this string as Main files (containing main())
MainFilesExtension = '.Main.cpp'

# Find all sources recursively
MainSourceFiles = []
ClassSourceFiles = []

for DirPath, DirNames, FileNames in os.walk('.'):
	if SourceSkipDirectories.count(DirPath):
		continue

	for FileName in FileNames:
		if SourceExtensions.count(os.path.splitext(FileName)[1]):
			FilePath = os.path.join(DirPath, FileName)

			if FileName.endswith(MainFilesExtension):
				MainSourceFiles.append(FilePath)
			else:
				ClassSourceFiles.append(FilePath)

# Create objects from SourceFiles
MainObjectFiles = {}
ClassObjectFiles = {}

for ClassSourceFile in ClassSourceFiles:
	ClassObjectFiles[ClassSourceFile] = os.path.join(BinDirectory, EscapePath(os.path.splitext(ClassSourceFile)[0]) + ".o")

for MainSourceFile in MainSourceFiles:
	MainObjectFiles[MainSourceFile] = os.path.join(BinDirectory, EscapePath(os.path.splitext(MainSourceFile)[0]) + ".o")

for ClassSourceFile, ClassObjectFile in ClassObjectFiles.iteritems():
	E.Object(ClassObjectFile, ClassSourceFile)

for MainSourceFile, MainObjectFile in MainObjectFiles.iteritems():
	E.Object(MainObjectFile, MainSourceFile)

# Create target executable
for MainSourceFile, MainObjectFile in MainObjectFiles.iteritems():
	TargetExecutableName = MainSourceFile[:-len(MainFilesExtension)]
	TargetExecutablePath = os.path.join(BinDirectory, TargetExecutableName)

	E.Program(TargetExecutablePath, [MainObjectFile] + ClassObjectFiles.values())